简介
(初稿)
Android NDK开发属于Android开发中的高阶内容,其不仅要熟悉Android平台知识,更需要熟悉C++语言和相关的构建工具。而NDK开发中出现的异常是Android APP crash的主要原因。NDK开发的异常调试和分析比较困难,日志信息可读性很差。因此本文对NDK开发中常用的工具和方法进行总结,以期能帮助大家提升Android NDK开发的水平。
首先,关于JNI和Android NDK开发,请务必先认真完成以下文章的阅读:
- JNI官方文档
- JNI Tips(Android官网JNI培训系列)
- NDK入门指南,从
Getting Started
开始看,每一个章节全部都不要遗漏。
Android NDK的调试和分析主要有以下几种方法:
- LLDB:原生调试,支持断点和变量查看,用于开发者有源码的情况下,多用于开发阶段;
- ndk-gdb:支持ndk-build脚本构建的工程,当前Android studio默认已采用CMake方式构建工程,所以不是很推荐;
- ndk-stack:适用于已经发布版本,或者用户反馈问题(提供了错误logcat日志)等情况,即直接分析NDK错误日志,分析C++源码的错误点。
- AddressSanitize:google官方提供的用于检测C/C++代码的memory error的工具(除了Android,其他平台也可以使用)。
- Native Tracing:对C++代码进行跟踪分析,比如执行时间和效率等等。使用非常简单,仅需要依赖Android的
#include <android/trace.h>
头文件即可。但仅在Android API Level>=23才支持。用于在开发阶段优化代码逻辑,提升算法质量等。
Note:推荐采用LLDB或ndk-stack
LLDB
请参见https://developer.android.com/studio/debug/
ndk-gdb
请参见https://developer.android.com/ndk/guides/ndk-gdb
ndk-stack
请参见https://developer.android.com/ndk/guides/ndk-stack
使用命令格式如下(其中,$NDK
代表NDK的安装目录,新版Android studio的SDK Manager会将NDK安装在Android SDK目录下的ndk-bundle
子目录,如果是自己单独下载NDK的话,请找到对应的解压路径。新版Android studio采用CMake构建,构建生成的so文件位于$PROJECT_PATH/app/build/intermediates/cmake/debug/obj/<abi>
下(debug模式)或$PROJECT_PATH/app/build/intermediates/cmake/debug/release/<abi>
(release模式),其中 <abi>
表示您的设备的ABI)。当然也可以直接从Android APK解压提取共享库so文件,然后存放在指定目录,以便分析。
adb logcat | $NDK/ndk-stack -sym $PROJECT_PATH/app/build/intermediates/cmake/debug/obj/<abi>
或者分开执行:
adb logcat > /tmp/foo.txt
$NDK/ndk-stack -sym $PROJECT_PATH/app/build/intermediates/cmake/debug/obj/<abi> -dump foo.txt
示例(以windows为例):
cd F:\ubuntu\share\V8Android\app\build\intermediates\cmake\debug\obj\arm64-v8a
“F:\Android\sdk\ndk-bundle\ndk-stack.cmd” -sym . -dump D:\UserProfiles\CoulsonChen\Desktop\ndk.txt >analyze.txt
analyze.txt的内容如下(从中可以明确看到出错的代码行在哪里):
********** Crash dump: **********
Build fingerprint: 'google/walleye/walleye:8.1.0/OPM1.171019.019/4527419:user/release-keys'
pid: 6740, tid: 6740, name: boyaa.v8wrapper >>> com.boyaa.v8wrapper <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x27
Stack frame #00 pc 000000000056f204 /data/app/com.boyaa.v8wrapper-gc82kSUIyk_jPb6OjAZERw==/lib/arm64/libnative-lib.so: Routine v8::base::Relaxed_Load(long const volatile*) at /home/ibon/v8/v8/out.gn/aar_lkgr_64/../../src/base/atomicops_internals_portable.h:168
Stack frame #01 pc 000000000056df00 /data/app/com.boyaa.v8wrapper-gc82kSUIyk_jPb6OjAZERw==/lib/arm64/libnative-lib.so: Routine v8::internal::(anonymous namespace)::InstantiateObject(v8::internal::Isolate*, v8::internal::Handle<v8::internal::ObjectTemplateInfo>, v8::internal::Handle<v8::internal::JSReceiver>, bool, bool) at /home/ibon/v8/v8/out.gn/aar_lkgr_64/../../src/api-natives.cc:375
Stack frame #02 pc 000000000056ddc4 /data/app/com.boyaa.v8wrapper-gc82kSUIyk_jPb6OjAZERw==/lib/arm64/libnative-lib.so: Routine v8::internal::ApiNatives::InstantiateObject(v8::internal::Handle<v8::internal::ObjectTemplateInfo>, v8::internal::Handle<v8::internal::JSReceiver>) at /home/ibon/v8/v8/out.gn/aar_lkgr_64/../../src/api-natives.cc:547
Stack frame #03 pc 00000000000f4774 /data/app/com.boyaa.v8wrapper-gc82kSUIyk_jPb6OjAZERw==/lib/arm64/libnative-lib.so: Routine v8::ObjectTemplate::NewInstance(v8::Local<v8::Context>) at /home/ibon/v8/v8/out.gn/aar_lkgr_64/../../src/api.cc:6733 (discriminator 2)
Stack frame #04 pc 00000000000cfa40 /data/app/com.boyaa.v8wrapper-gc82kSUIyk_jPb6OjAZERw==/lib/arm64/libnative-lib.so (WrapGamerObject(v8::Isolate*, Gamer*)+588): Routine WrapGamerObject(v8::Isolate*, Gamer*) at F:\ubuntu\share\V8Android\app\src\main\cpp/util.cpp:208
Stack frame #05 pc 00000000000d22cc /data/app/com.boyaa.v8wrapper-gc82kSUIyk_jPb6OjAZERw==/lib/arm64/libnative-lib.so (initV8()+792): Routine initV8() at F:\ubuntu\share\V8Android\app\src\main\cpp/native-lib.cpp:67
Stack frame #06 pc 00000000000d35d0 /data/app/com.boyaa.v8wrapper-gc82kSUIyk_jPb6OjAZERw==/lib/arm64/libnative-lib.so (Java_com_boyaa_v8wrapper_MainActivity_nativeInit+72): Routine Java_com_boyaa_v8wrapper_MainActivity_nativeInit at F:\ubuntu\share\V8Android\app\src\main\cpp/native-lib.cpp:165
Stack frame #07 pc 00000000000092b8 /data/app/com.boyaa.v8wrapper-gc82kSUIyk_jPb6OjAZERw==/oat/arm64/base.odex (offset 0x9000)